package structuralPattern.adapter;

/**
 * @Author: Alex Hu
 * Date: 2020/2/22 4:49 下午
 * Content: 双向适配器模式示例
 * 设计意图：同时实现两个接口，使得两个不兼容的接口可以互相转换
 * 使用场景：当需要两个不兼容的接口互相转换时使用
 */

/**
 * 目标接口
 * 设计意图：定义客户所期望的接口
 * 使用场景：当需要定义统一的接口规范时使用
 */
interface TwoWayTarget {
    /**
     * 请求方法
     * 设计意图：定义客户期望的请求方法
     * 使用场景：当需要发送请求时调用
     */
    void request();
}

/**
 * 适配者接口
 * 设计意图：定义需要被适配的接口
 * 使用场景：当需要被适配的接口具有不兼容的方法时使用
 */
interface TwoWayAdaptee {
    /**
     * 特殊请求方法
     * 设计意图：定义适配者的特殊请求方法
     * 使用场景：当需要发送特殊请求时调用
     */
    void specificRequest();
}

/**
 * 目标实现类
 * 设计意图：实现目标接口
 * 使用场景：当需要提供目标接口的具体实现时使用
 */
class TargetRealize implements TwoWayTarget {
    /**
     * 请求方法
     * 设计意图：实现目标接口的请求方法
     * 使用场景：当需要发送请求时调用
     */
    public void request() {
        System.out.println("目标代码被调用！");
    }
}

/**
 * 适配者实现类
 * 设计意图：实现适配者接口
 * 使用场景：当需要提供适配者接口的具体实现时使用
 */
class AdapteeRealize implements TwoWayAdaptee {
    /**
     * 特殊请求方法
     * 设计意图：实现适配者接口的特殊请求方法
     * 使用场景：当需要发送特殊请求时调用
     */
    public void specificRequest() {
        System.out.println("适配者代码被调用！");
    }
}

/**
 * 双向适配器
 * 设计意图：同时实现目标接口和适配者接口
 * 使用场景：当需要两个不兼容的接口互相转换时使用
 */
class TwoWayAdapter implements TwoWayTarget, TwoWayAdaptee {
    /**
     * 目标对象
     * 设计意图：存储目标对象
     * 使用场景：当需要通过目标对象发送请求时使用
     */
    private TwoWayTarget target;

    /**
     * 适配者对象
     * 设计意图：存储适配者对象
     * 使用场景：当需要通过适配者对象发送特殊请求时使用
     */
    private TwoWayAdaptee adaptee;

    /**
     * 构造函数
     * 设计意图：初始化适配者对象
     * 使用场景：当需要创建双向适配器时调用
     * @param adaptee 适配者对象
     */
    public TwoWayAdapter(TwoWayAdaptee adaptee) {
        this.adaptee = adaptee;
    }

    /**
     * 构造函数
     * 设计意图：初始化目标对象
     * 使用场景：当需要创建双向适配器时调用
     * @param target 目标对象
     */
    public TwoWayAdapter(TwoWayTarget target) {
        this.target = target;
    }

    /**
     * 请求方法
     * 设计意图：实现目标接口的请求方法，调用适配者的特殊请求方法
     * 使用场景：当需要将特殊请求转换为标准请求时调用
     */
    public void request() {
        adaptee.specificRequest();
    }

    /**
     * 特殊请求方法
     * 设计意图：实现适配者接口的特殊请求方法，调用目标的请求方法
     * 使用场景：当需要将标准请求转换为特殊请求时调用
     */
    public void specificRequest() {
        target.request();
    }
}

/**
 * 客户端代码
 * 设计意图：演示双向适配器模式
 * 使用场景：当需要测试或演示双向适配器模式时调用
 */
public class TwoWayAdapterTest {
    /**
     * 主方法：演示双向适配器模式
     * 设计意图：通过双向适配器实现两个不兼容接口的互相转换
     * 使用场景：当需要测试或演示双向适配器模式时调用
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        System.out.println("目标通过双向适配器访问适配者：");
        TwoWayAdaptee adaptee = new AdapteeRealize();
        TwoWayTarget target = new TwoWayAdapter(adaptee);
        target.request();
        System.out.println("-------------------");
        System.out.println("适配者通过双向适配器访问目标：");
        target = new TargetRealize();
        adaptee = new TwoWayAdapter(target);
        adaptee.specificRequest();
    }
}
